package com.ajavaer.framework.core.orm.service.impl;

import com.ajavaer.framework.core.orm.dao.BaseDAO;
import com.ajavaer.framework.core.orm.service.BaseService;
import com.ajavaer.framework.core.request.PagingRequest;
import com.ajavaer.framework.core.request.RequestFilter;
import com.ajavaer.framework.core.request.RequestSpecification;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseServiceImpl<T, ID extends Serializable> implements BaseService<T, ID> {
    private BaseDAO<T, ID> baseDAO;

    @Resource
    private EntityManager entityManager;

    public BaseServiceImpl(BaseDAO<T, ID> baseDAO) {
        this.baseDAO = baseDAO;
    }

    @Override
    public Page<T> findPaging(Integer page, Integer rows, Map<String, Object> searchParams, Sort sort) {
        return findPaging(page, rows, buildSpecification(searchParams), sort);
    }

    @Override
    @SuppressWarnings("unchecked")
    public Page<T> findPaging(Integer page, Integer rows, Specification specification, Sort sort) {
        return baseDAO.findAll(specification, PageRequest.of(page - 1, rows, sort));
    }

    @Override
    public Page<T> findPaging(PagingRequest request) {
        return findPaging(request.getPage(), request.getLimit(), request.getSearch(), request.sort());
    }

    @Override
    public List<T> findAll(Map<String, Object> searchParams) {
        return findAll(searchParams, Sort.unsorted());
    }

    @Override
    public List<T> findAll(Map<String, Object> searchParams, Sort sort) {
        Specification<T> spec = buildSpecification(searchParams);
        return findAll(spec, sort);
    }

    @Override
    public List<T> findAll(Specification<T> spec, Sort sort) {
        if (sort != null) {
            return baseDAO.findAll(spec, sort);
        } else {
            return baseDAO.findAll(spec);
        }
    }

    @Override
    public List<T> findAll() {
        return baseDAO.findAll();
    }

    @Override
    public List<T> findByProperty(String property, Object value, Sort sort) {
        Map<String, Object> searchParams = new HashMap<>();
        searchParams.put(property, value);
        return findAll(searchParams, sort);
    }

    @Override
    public List<T> findByProperty(String property, Object value) {
        return findByProperty(property, value, Sort.unsorted());
    }

    /**
     * 创建动态查询条件组合.
     */
    private Specification<T> buildSpecification(Map<String, Object> searchParams) {
        return new RequestSpecification<>(RequestFilter.parse(searchParams).values());
    }

    @Override
    public T getById(ID id) {
        return baseDAO.getById(id);
    }

    @Override
    public T saveOrUpdate(T entity) {
        return baseDAO.saveAndFlush(entity);
    }

    @Override
    public void delete(T entity) {
        baseDAO.delete(entity);
    }

    @Override
    public void delete(ID id) {
        baseDAO.deleteById(id);
    }

    @Override
    public void delete(Iterable<T> entites) {
        baseDAO.deleteInBatch(entites);
    }

    @Override
    public void delete(Collection<ID> ids) {
        List<T> dbList = baseDAO.findAllById(ids);
        baseDAO.deleteInBatch(dbList);
    }

    @Override
    public boolean exists(Example<T> entity) {
        return baseDAO.exists(entity);
    }

    @Override
    public void deleteByIdIn(Collection<ID> idList) {
        delete(idList);
    }

    @Override
    public EntityManager getEntityManager() {
        return entityManager;
    }

}